#ifndef _QQCLIENT_H
#define _QQCLIENT_H

#include <vector>
#include <QMutex>
#include <time.h>
#include "qqdef.hpp"
#include "packetmgr.hpp"
#include "buddy.hpp"
#include "qqsocket.hpp"
#include "protocol.hpp"
#include <QThread>
#include <string>

//login process
enum LOGIN_PROCESS{
	P_INIT = 0,
	P_LOGGING,
	P_VERIFYING,
	P_LOGIN,
	P_ERROR,
	P_DENIED,
	P_WRONGPASS,
	P_BUSY
};


class server_item{
public:
	char	ip[32];
	ushort	port;
};

class qunmember;
class qqgroup;
class qqqun;

class qqclient:public QObject{
	Q_OBJECT
public:
	uint		number;
	ushort		version;
	QMutex		seqno_lock;
	ushort		seqno;
	int			socket;
	char		password[64];
	uchar		md5_pass1[16];
	uchar		md5_pass2[16];
	uint		server_ip;
	ushort		server_port;
	uint		proxy_server_ip;
	ushort		proxy_server_port;
	uchar		proxy_established;
	uint		client_ip;
	ushort		client_port;
	uint		local_ip;
	ushort		local_port;
	uint		last_login_ip;
	uint		last_login_time;
	uint		login_time;
	uint		server_time;
	char		mode;
	char		has_camera;
	int			process;
	char		log_terminal;
	char		log_packet;
	QThread*	thread_keepalive;
	qqpacketmgr	packetmgr;
	qqbuddy*	self;
	//buddy qun group
	QMutex		buddy_list_lock;
	QMutex		qun_list_lock;
	QMutex		group_list_lock;
	typedef std::vector<qqbuddy*> buddy_list_type;
	buddy_list_type		buddy_list;
	typedef std::vector<qqqun*> qun_list_type;
	qun_list_type		qun_list;
	typedef std::vector<qqgroup*> group_list_type;
	group_list_type		group_list;
	uint		online_clock;
	char		verify_dir[PATH_LEN];
	ushort		level;
	ushort		active_days;
	ushort		upgrade_days;
	QMutex		event_list_lock;
	std::list<std::string> event_loop;

	char		network;	//TCP or UDP
	char		login_finish;
	char		auto_accept;	//accept addbuddy requests
	char		auto_reply[AUTO_REPLY_LEN];
	int			http_sock;
	union{
		struct qqdata_2009	data;
	};
	int		keep_alive_counter;
	qqclient(){
		this->number=0;
this->version=0;
this->seqno=0;
this->socket=0;
memset(this->password,0,sizeof(this->password));
memset(this->md5_pass1,0,sizeof(this->md5_pass1));
memset(this->md5_pass2,0,sizeof(this->md5_pass2));
this->server_ip=0;
this->server_port=0;
this->proxy_server_ip=0;
this->proxy_server_port=0;
this->proxy_established=0;
this->client_ip=0;
this->client_port=0;
this->local_ip=0;
this->local_port=0;
this->last_login_ip=0;
this->last_login_time=0;
this->login_time=0;
this->server_time=0;
this->mode=0;
this->has_camera=0;
this->process=0;
this->log_terminal=0;
this->log_packet=0;
//this->thread_keepalive=0;
//this->packetmgr=0;
this->self=0;
//this->buddy_list=0;
//this->qun_list=0;
//this->group_list=0;
this->online_clock=0;
memset(this->verify_dir,0,PATH_LEN);
this->level=0;
this->active_days=0;
this->upgrade_days=0;
//this->event_loop=0;
//this->msg_loop=0;
this->network=0;	
this->login_finish=0;
this->auto_accept=0;	
memset(this->auto_reply,0,AUTO_REPLY_LEN);
this->http_sock=0;
this->keep_alive_counter=0;
	}
};


int qqclient_create( qqclient* qq, uint num, char* pass ); 
int qqclient_md5_create( qqclient* qq, uint num, uchar* md5_pass ); 
int qqclient_login( qqclient* qq );
void qqclient_logout( qqclient* qq );
void qqclient_detach( qqclient* qq );
void qqclient_cleanup( qqclient* qq );
int qqclient_verify( qqclient* qq, const char* code );
int qqclient_wait( qqclient* qq, int sec );
void qqclient_change_status( qqclient* qq, uchar mode );
int qqclient_get_event( qqclient* qq, char* event, int size, int wait );
int qqclient_put_event( qqclient* qq, char* event );
void qqclient_set_process( qqclient *qq, int process );

void qqclient_get_server( qqclient* qq );
int qqclient_add( qqclient* qq, uint number, char* request_str );
int qqclient_del( qqclient* qq, uint number );
void qqclient_keepalive(qqclient* qq);

 class MyKeepAliveThread : public QThread
 {
	Q_OBJECT
 public:
	 MyKeepAliveThread(qqclient* q):qq(q){};
 protected:
     void run();
public slots:
    void OnTerminate();
 private:
	 qqclient* qq;
 };


#endif
